/*
 * Copyright 2010-2011 WebEqua Team
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package org.mathcloud.math.core.matlab.quantity;

//import classes slf4j
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

//import classes org.webequa.core.common
import org.webequa.core.common.quantity.ComplexMatrix;
import org.webequa.core.common.quantity.ComplexNumber;
import org.webequa.core.common.quantity.QuantityObject;
import org.webequa.core.common.quantity.RealMatrix;
import org.webequa.core.common.quantity.RealNumber;

//import classes org.webequa.core.generic
import org.webequa.core.generic.signature.GenericQuantityObjectSignature;

//import classes com.mathworks.toolbox.javabuilder
import com.mathworks.toolbox.javabuilder.MWClassID;
import com.mathworks.toolbox.javabuilder.MWComplexity;
import com.mathworks.toolbox.javabuilder.MWNumericArray;


public class MatlabComplexMatrix extends MatlabQuantityObject implements ComplexMatrix
{		
	public MatlabComplexMatrix(Integer rows, Integer cols)
	{
		super();
		try
		{
			mtlbObject = MWNumericArray.newInstance(new int[]{rows, cols}, MWClassID.DOUBLE, MWComplexity.COMPLEX);
			log.info("{}={}",mtlbVarName,mtlbObject.toString());
			signature = GenericQuantityObjectSignature.getComplexMatrixSignature();
			((GenericQuantityObjectSignature)signature).setDimensions(mtlbObject.getDimensions());
			signature.setRealizationName("matlab");
		} catch (Exception e)
		{
			log.error("Exception:",e);
		}
	}
	
	public MatlabComplexMatrix(double[][] arg0, double[][] arg1)
	{
		super();		
		try
		{
			mtlbObject = new MWNumericArray(arg0, arg1, MWClassID.DOUBLE);
			log.info("{}={}",mtlbVarName,mtlbObject.toString());
			signature = GenericQuantityObjectSignature.getComplexMatrixSignature();
			((GenericQuantityObjectSignature)signature).setDimensions(mtlbObject.getDimensions());
			signature.setRealizationName("matlab");
		} catch (Exception e)
		{
			log.error("Exception",e);
		}
	}
	
	public MatlabComplexMatrix(RealMatrix arg0, RealMatrix arg1)
	{
		super();		
		
		if(arg0 != null && arg1 != null) {
		
		try
		{
			int[] dinarg0 = {arg0.getNumberOfRows(), arg0.getNumberOfCols()};
			int[] dinarg1 = {arg1.getNumberOfRows(), arg1.getNumberOfCols()};
			int   rows    = (dinarg0[0]>dinarg1[0])?dinarg0[0]:dinarg1[0];
			int   cols    = (dinarg0[1]>dinarg1[1])?dinarg0[1]:dinarg1[1];
			
			double[][] real = new double[rows][cols];
			double[][] imag = new double[rows][cols];
			
			for(int i=0; i<rows; i++) {
				for(int j=0; j<cols; j++) {
					real[i][j] = (i<dinarg0[0] && j<dinarg0[1])?((RealNumber)arg0.getMatrixElement(i, j)).getValue():0;
					imag[i][j] = (i<dinarg1[0] && j<dinarg1[1])?((RealNumber)arg1.getMatrixElement(i, j)).getValue():0;
				}
			}
			mtlbObject = new MWNumericArray(real, imag, MWClassID.DOUBLE);
			log.info("{}={}",mtlbVarName,mtlbObject.toString());
			signature = GenericQuantityObjectSignature.getComplexMatrixSignature();
			((GenericQuantityObjectSignature)signature).setDimensions(mtlbObject.getDimensions());
			signature.setRealizationName("matlab");
		} catch (Exception e)
		{
			log.error("Exception",e);
		}
		}
		else {
			log.warn("One of objects isn't defined");
		}
	}	

	
	public MatlabComplexMatrix(RealMatrix arg0)
	{
		super();
		if (arg0!=null)
		{
			try 
			
			{
				if (arg0.getSignature().getRealizationName().equalsIgnoreCase("matlab"))
				{
					log.debug("Signatures of objects is equivalent");
					mtlbObject = (MWNumericArray) ((MatlabRealMatrix)arg0).getMatlabObject().clone();
					log.info("{}={}",mtlbVarName,((MatlabComplexMatrix)arg0).getVarName());
				}
				else {
					log.debug("Signatures of objects isn't equivalent");
					int rows = arg0.getNumberOfRows();
					int cols = arg0.getNumberOfCols();

					mtlbObject = MWNumericArray.newInstance(new int[] {rows,cols}, MWClassID.DOUBLE, MWComplexity.COMPLEX);
					
					for (int i=0; i<rows; i++)
						for (int j=0; j<cols; j++)  
							setMatrixElement((ComplexNumber)arg0.getMatrixElement(i, j), i, j);
					
					log.info("{}={}",mtlbVarName,((MatlabRealMatrix)arg0).getVarName());
				}
				signature = GenericQuantityObjectSignature.getComplexMatrixSignature();
				((GenericQuantityObjectSignature)signature).setDimensions(mtlbObject.getDimensions());
				signature.setRealizationName("matlab");
			} catch (Exception e)
			{
				log.error("Exception",e);
			}
		}	
		else {
				log.warn("Objects isn't defined");
			}			
	}	
	
	
	public MatlabComplexMatrix(ComplexMatrix arg0)
	{
		super();
		if (arg0!=null)
		{
			try 
			
			{
				if (arg0.getSignature().getRealizationName().equalsIgnoreCase("matlab"))
				{
					log.debug("Signatures of objects is equivalent");
					mtlbObject = (MWNumericArray) ((MatlabComplexMatrix)arg0).getMatlabObject().clone();
					log.info("{}={}",mtlbVarName,((MatlabComplexMatrix)arg0).getVarName());
				}
				else {
					log.debug("Signatures of objects isn't equivalent");
					int rows = arg0.getNumberOfRows();
					int cols = arg0.getNumberOfCols();

					mtlbObject = MWNumericArray.newInstance(new int[] {rows,cols}, MWClassID.DOUBLE, MWComplexity.COMPLEX);
					
					for (int i=0; i<rows; i++)
						for (int j=0; j<cols; j++)  
							setMatrixElement((ComplexNumber)arg0.getMatrixElement(i, j), i, j);
					
					log.info("{}={}",mtlbVarName,((MatlabRealMatrix)arg0).getVarName());
				}
				signature = GenericQuantityObjectSignature.getComplexMatrixSignature();
				((GenericQuantityObjectSignature)signature).setDimensions(mtlbObject.getDimensions());
				signature.setRealizationName("matlab");
			} catch (Exception e)
			{
				log.error("Exception",e);
			}
		}	
		else {
				log.warn("Objects isn't defined");
			}			
	}
	
	public int getNumberOfRows()
	{
		if (mtlbObject!=null) {
			return mtlbObject.getDimensions()[0];
		}
	  	else {
	  	  	log.warn("The object isn't defined");
	  	  	}
		return 0;
	}
	
	public int getNumberOfCols()
	{
		if (mtlbObject!=null) {
			return mtlbObject.getDimensions()[1];
		}
	  	else {
	  	  	log.warn("The object isn't defined");
	  	  	}
		return 0;
	}
	
	public QuantityObject getMatrixElement(int i, int j)
	{
		if (mtlbObject!=null)
		{
			if (i<getNumberOfRows() && 
				j<getNumberOfCols() && 
				i>=0 				&& 
				j>=0 )
			{	int []dims = {i+1, j+1};
				return new MatlabComplexNumber(((MWNumericArray)mtlbObject).getDouble(dims),((MWNumericArray)mtlbObject).getImagDouble(dims));
			}  		
			else {
				log.warn("Attempt to use an index({},{}) that is less than zero or greater than or equal to the length of the Matrix",i,j);
			}
		}
		else {
			log.warn("The object isn't defined");
		}
		return null;
	}
	
	@Override
	public RealMatrix getImagePart()
	{
		if (mtlbObject!=null) {
			return new MatlabRealMatrix((double[][])((MWNumericArray)mtlbObject).toImagDoubleArray());
		}
	  	else {
	  	  	log.warn("The object isn't defined");
	  	  	}
		return null;
	}

	@Override
	public RealMatrix getRealPart()
	{
		if (mtlbObject!=null) {
			return new MatlabRealMatrix((double[][])((MWNumericArray)mtlbObject).toDoubleArray());
		}
	  	else {
	  	  	log.warn("The object isn't defined");
	  	  	}
		return null;
	}

	@Override
	public void setMatrixElement(ComplexNumber arg0, int i, int j)
	{
		if ((mtlbObject!=null) && (arg0!=null))
		{  		
			if (i<=getNumberOfRows() 	&&
				j<=getNumberOfCols() 	&&
				i>=0					&&
				j>=0)
			{
				try
				{
					int []dims = {i+1, j+1};
					((MWNumericArray)mtlbObject).set(dims, arg0.getRealPart());
					((MWNumericArray)mtlbObject).setImag(dims, arg0.getImagePart());
					log.info("{}("+i+","+j+")={}",mtlbVarName, arg0.getValue());

				} catch (Exception e)
				{
					log.error("Exception",e);
				}  				
			}
			else {
				log.warn("Attempt to use an index({},{}) that is less than zero or greater than or equal to the length of the Matrix",i,j);
			}
		}	
		else {
			log.warn("One of objects isn't defined");
		}			
	}
	
	public void setMatrixElement(RealNumber arg0, int i, int j)
	{
		if ((mtlbObject!=null) && (arg0!=null))
		{  		
			if (i<=getNumberOfRows() 	&&
				j<=getNumberOfCols() 	&&
				i>=0					&&
				j>=0)
			{
				try
				{
					int []dims = {i+1, j+1};
					((MWNumericArray)mtlbObject).set(dims, arg0.getValue());
					((MWNumericArray)mtlbObject).setImag(dims, 0);
					log.info("{}("+i+","+j+")={}",mtlbVarName, arg0.getValue());

				} catch (Exception e)
				{
					log.error("Exception",e);
				}  				
			}
			else {
				log.warn("Attempt to use an index({},{}) that is less than zero or greater than or equal to the length of the Matrix",i,j);
			}
		}	
		else {
			log.warn("One of objects isn't defined");
		}
	}
	
	private static final Logger log = LoggerFactory.getLogger(MatlabComplexMatrix.class);	
}
